/*
 * interfaz.c
 *
 *  Created on: 06/10/2011
 *      Author: utn_so
 */


#include "interfaz.h"

int32_t AgregarPedido (stNodoPedido **listaPedidos,stPedido *pedido,
						char **algoritmo,int32_t *agregadosEjecucion,
						stNodoPedido **listaEjecutar, stNodoSincro **listaSincro,
						int32_t *contadorEjecutar, sem_t *semaforoContador)
{

	stNodoPedido *nuevo,*ptr;
	if(strncmp((*algoritmo),"SSTF",4) == 0)
	{

		nuevo = (stNodoPedido *)malloc(sizeof(stNodoPedido));
		nuevo->info = pedido;
		nuevo->sgte=NULL;

		if((*listaPedidos) != NULL && (*listaPedidos)->info != NULL){
			for(ptr = *listaPedidos; ptr->sgte; ptr=ptr->sgte );
			ptr->sgte = nuevo;
		}else
		{
			//(*listaPedidos)->info=nuevo->info;
			(*listaPedidos)=nuevo;
		}
		sem_post(semaforoContador);

	}
	else
	{
/*if((*listaPedidos) == NULL || (*listaPedidos)->info == NULL )
{
	*agregadosEjecucion = 0;
	*contadorEjecutar =10;
}*/

		if (*agregadosEjecucion < 10 ||
				(*listaEjecutar) == NULL ||
				(*listaEjecutar)->info == NULL )
		{
			if (pedido->tipoOperacion != ESCRIBIR)
			{
				//escribo en listaejecutar
				nuevo = (stNodoPedido *)malloc(sizeof(stNodoPedido));
				nuevo->info = pedido;
				nuevo->sgte=NULL;

				if((*listaEjecutar) != NULL && (*listaEjecutar)->info != NULL){
					for(ptr = *listaEjecutar; ptr->sgte; ptr=ptr->sgte );
					ptr->sgte = nuevo;
				}else
				{
					(*listaEjecutar)=nuevo;
				}
				*agregadosEjecucion =*agregadosEjecucion+1 ;
				sem_post(semaforoContador);
			}
			else
			{
				if(buscarSectorListaSincro(pedido,listaSincro)== 1)
				{
					//escribo en listaejecutar
					nuevo = (stNodoPedido *)malloc(sizeof(stNodoPedido));
					nuevo->info = pedido;
					nuevo->sgte=NULL;

					if((*listaEjecutar) != NULL && (*listaEjecutar)->info != NULL){
						for(ptr = *listaEjecutar; ptr->sgte; ptr=ptr->sgte );
						ptr->sgte = nuevo;
					}else
					{
						(*listaEjecutar)=nuevo;
					}
					*agregadosEjecucion =*agregadosEjecucion+1 ;
					sem_post(semaforoContador);
				}
				else
				{
					//escribo en listapedido
					nuevo = (stNodoPedido *)malloc(sizeof(stNodoPedido));
					nuevo->info = pedido;
					nuevo->sgte=NULL;

					if((*listaPedidos) != NULL && (*listaPedidos)->info != NULL){
						for(ptr = *listaPedidos; ptr->sgte; ptr=ptr->sgte );
						ptr->sgte = nuevo;
					}else
					{
						(*listaPedidos)=nuevo;
					}
				}
			}

		}
		else
		{
			//escribo en listapedido
			nuevo = (stNodoPedido *)malloc(sizeof(stNodoPedido));
			nuevo->info = pedido;
			nuevo->sgte=NULL;

			if((*listaPedidos) != NULL && (*listaPedidos)->info != NULL){
				for(ptr = *listaPedidos; ptr->sgte; ptr=ptr->sgte );
				ptr->sgte = nuevo;
			}else
			{
				(*listaPedidos)=nuevo;
			}
		}


	}


	//printf("agrego el pedido! sector: %ld  tipo operacion: %d\n",pedido->sector,pedido->tipoOperacion);
	return 1;

}

int32_t AgregarPedidoSincro (stNodoSincro **listaSincro,long sector)
{

	return 1;
	stNodoSincro *nuevo,*ptr;

	nuevo = (stNodoSincro *)malloc(sizeof(stNodoSincro));
	nuevo->sector = sector;
	nuevo->sgte=NULL;

	if((*listaSincro) != NULL && (*listaSincro)->sector != NULL){
		for(ptr = *listaSincro; ptr->sgte; ptr=ptr->sgte );
		ptr->sgte = nuevo;
	}else
	{
		(*listaSincro)=nuevo;
	}


	return 1;

}


long modulo (long numero)
{
if (numero < 0)
	numero = numero * (-1);

return numero;
}

stPedido* proximoPedidoSSTF(stNodoPedido **listaPedidos, chs **posicionActual,
		chs datosConfig)
{
	stNodoPedido *aux;
	stPedido *resultado;
	long evaluando;
	long proximo;
	chs *proximoSector = (chs *)malloc(sizeof(chs));
	chs *evaluandoSector = (chs *)malloc(sizeof(chs));
	resultado = (*listaPedidos)->info;
	obtenerCHSDif((*listaPedidos)->info->sector,datosConfig,proximoSector);

	 if(proximoSector->c == (*posicionActual)->c)
	 {
		free(proximoSector);
		free(evaluandoSector); //no va a menos q descomentemos arriba

		return resultado;
	 }

	aux = (*listaPedidos);
	while(aux != NULL && aux->sgte != NULL )
	{

		aux= aux->sgte;

		proximo = proximoSector->c - (*posicionActual)->c;
		obtenerCHSDif(aux->info->sector,datosConfig,evaluandoSector);
		evaluando = evaluandoSector->c - (*posicionActual)->c;

		if(modulo(proximo) > modulo(evaluando))
		{
			proximoSector->c = evaluandoSector->c;
			proximoSector->h = evaluandoSector->h;
			proximoSector->s = evaluandoSector->s;
			proximoSector->seekTime = evaluandoSector->seekTime;

			resultado = aux->info;
		}
		//free(evaluandoSector);
	}


	free(proximoSector);
	free(evaluandoSector);


	return resultado;

}

stPedido* proximoPedidoSSTFConOmision(stNodoPedido **listaPedidos, chs **posicionActual,
		chs datosConfig,stPedido *omitir)
{
	stNodoPedido *aux;
	stPedido *resultado;
	long evaluando;
	long proximo;
	chs *proximoSector = (chs *)malloc(sizeof(chs));
	chs *evaluandoSector = (chs *)malloc(sizeof(chs));
	resultado = (*listaPedidos)->info;
	obtenerCHSDif((*listaPedidos)->info->sector,datosConfig,proximoSector);

	if(resultado->tipoOperacion != omitir->tipoOperacion &&
			resultado->sector != omitir->sector)
	{
		 if(proximoSector->c == (*posicionActual)->c)
		 {
			free(proximoSector);
			free(evaluandoSector); //no va a menos q descomentemos arriba

			return resultado;
		 }
	}
	aux = (*listaPedidos);
	while(aux != NULL && aux->sgte != NULL )
	{

		aux= aux->sgte;
		if (aux->info->tipoOperacion != omitir->tipoOperacion &&
				aux->info->sector != omitir->sector)
		{
			proximo = proximoSector->c - (*posicionActual)->c;
			obtenerCHSDif(aux->info->sector,datosConfig,evaluandoSector);
			evaluando = evaluandoSector->c - (*posicionActual)->c;

			if(modulo(proximo) > modulo(evaluando))
			{
				proximoSector->c = evaluandoSector->c;
				proximoSector->h = evaluandoSector->h;
				proximoSector->s = evaluandoSector->s;
				proximoSector->seekTime = evaluandoSector->seekTime;

				resultado = aux->info;
			}
		}
		//free(evaluandoSector);
	}


	free(proximoSector);
	free(evaluandoSector);


	return resultado;

}

stPedido* proximoPedidoSSTFSincro(stNodoPedido **listaPedidos, chs **posicionActual,
		chs datosConfig, stNodoSincro **listaSincro)
{
	stPedido *resultado = (*listaPedidos)->info;
	return resultado;
}

/*
stPedido* proximoPedidoSSTFSincro(stNodoPedido **listaPedidos, chs **posicionActual,
		chs datosConfig, stNodoSincro **listaSincro)
{
	stNodoPedido *aux;
	stPedido *resultado;
	long evaluando;
	long proximo;
	chs *proximoSector = (chs *)malloc(sizeof(chs));
	chs *evaluandoSector = (chs *)malloc(sizeof(chs));
	resultado = (*listaPedidos)->info;
	obtenerCHSDif((*listaPedidos)->info->sector,datosConfig,proximoSector);

	////preguntar si es tipo evaluando->tipoOp SINCRO,, sigue todo igual

	if((*listaPedidos)->info->tipoOperacion == SINCROESCRIBIR)
	{

		 if(proximoSector->c == (*posicionActual)->c)
		 {
			free(proximoSector);
			free(evaluandoSector);

			return resultado;
		 }
	}
	else
	{
		//buscar el sector en listaSincro,
		if(buscarSectorListaSincro((*listaPedidos)->info,listaSincro) == 1)
		{
			 if(proximoSector->c == (*posicionActual)->c)
			 {
				free(proximoSector);
				free(evaluandoSector);

				return resultado;
			 }
		}
		else
		{
			//siga buscando...
		}
	}

	aux = (*listaPedidos);
	while(aux != NULL && aux->sgte != NULL)
	{

		aux= aux->sgte;

		proximo = proximoSector->c - (*posicionActual)->c;
		obtenerCHSDif(aux->info->sector,datosConfig,evaluandoSector);
		evaluando = evaluandoSector->c - (*posicionActual)->c;
////preguntar si es tipo evaluando->tipoOp SINCRO,, sigue todo igual

		if(aux->info->tipoOperacion == SINCROESCRIBIR)
		{
			//sigo como en el algoritmo original
			if(modulo(proximo) > modulo(evaluando))
			{
				proximoSector->c = evaluandoSector->c;
				proximoSector->h = evaluandoSector->h;
				proximoSector->s = evaluandoSector->s;
				proximoSector->seekTime = evaluandoSector->seekTime;
				resultado = aux->info;
			}
		}
		else
		{
			//buscar el sector en listaSincro,
			if(buscarSectorListaSincro(aux->info,listaSincro) == 1)
			{
				//sigo como en el algoritmo original
				if(modulo(proximo) > modulo(evaluando))
				{
					proximoSector->c = evaluandoSector->c;
					proximoSector->h = evaluandoSector->h;
					proximoSector->s = evaluandoSector->s;
					proximoSector->seekTime = evaluandoSector->seekTime;
					resultado = aux->info;
				}
			}
			else
			{
				//que siga buscando
			}
		}

	}


	free(proximoSector);
	free(evaluandoSector);


	return resultado;

}

*/


stPedido* proximoPedidoNSTEP(stNodoPedido **listaEjecutar, chs **posicionActual,
		chs datosConfig, int32_t *sentidoGiro)
{
	//HAY QE SABER PARA QUE LADO ESTA RECORRIENDO, si no hay mas por ese lado
	//tiene qe llegar al final ya sea 0 o cantSectores - 1
	//y ahi cambiar el sentido y volver  a empezar listaEjecutar para recorrer

	stNodoPedido *aux;
	stPedido *resultado;
	long evaluando;
	long proximo;
	chs *proximoSector = (chs *)malloc(sizeof(chs));
	chs *evaluandoSector= (chs *)malloc(sizeof(chs));
	resultado = (*listaEjecutar)->info;
	obtenerCHSDif((*listaEjecutar)->info->sector,datosConfig,proximoSector );

	aux = (*listaEjecutar);
	while(aux != NULL && aux->info != NULL)
	{
		proximo = proximoSector->c - (*posicionActual)->c;
		 obtenerCHSDif(aux->info->sector,datosConfig,evaluandoSector );
		evaluando = evaluandoSector->c - (*posicionActual)->c;

		if((*sentidoGiro) == 1)
		{
			if(evaluando >= 0 && proximo > evaluando)
			{
				proximoSector->c = evaluandoSector->c;
				proximoSector->h = evaluandoSector->h;
				proximoSector->s = evaluandoSector->s;
				proximoSector->seekTime = evaluandoSector->seekTime;
				resultado = aux->info;
			}
		}
		else if((*sentidoGiro) == -1)
		{
			if(evaluando <= 0 && proximo < evaluando)
			{
				proximoSector->c = evaluandoSector->c;
				proximoSector->h = evaluandoSector->h;
				proximoSector->s = evaluandoSector->s;
				proximoSector->seekTime = evaluandoSector->seekTime;
				resultado = aux->info;
			}
		}
//verificar si hay alguno qe cumplio si no, fin  y dar vuelta el sentido
//y volver a asginar a aux...
		if(aux->sgte == NULL)
		{
			if((*sentidoGiro) == 1 && proximo < 0)
			{

				aux = (*listaEjecutar);
				(*sentidoGiro) = -1;
				(*posicionActual)->c = datosConfig.c -1;
				obtenerCHSDif(aux->info->sector,datosConfig,proximoSector);
			}
			else if((*sentidoGiro) == -1 && proximo > 0)
			{

				aux = (*listaEjecutar);
				(*sentidoGiro) = 1;
				(*posicionActual)->c = 0;
				obtenerCHSDif(aux->info->sector,datosConfig,proximoSector);
			}
			else
			{
				break;
			}
		}
		aux= aux->sgte;
	//	if(evaluandoSector != NULL)
		//	free(evaluandoSector);
	}

//TODO: REVISAR FREE URGENTE!!!
	free(proximoSector);
		free(evaluandoSector);

	return resultado;
}



stPedido* proximoPedidoNSTEPConOmision(stNodoPedido **listaEjecutar, chs **posicionActual,
		chs datosConfig, int32_t *sentidoGiro, stPedido *omitir)
{
	//HAY QE SABER PARA QUE LADO ESTA RECORRIENDO, si no hay mas por ese lado
	//tiene qe llegar al final ya sea 0 o cantSectores - 1
	//y ahi cambiar el sentido y volver  a empezar listaEjecutar para recorrer

	stNodoPedido *aux;
	stPedido *resultado;
	long evaluando;
	long proximo;
	chs *proximoSector = (chs *)malloc(sizeof(chs));
	chs *evaluandoSector= (chs *)malloc(sizeof(chs));
	resultado = (*listaEjecutar)->info;
	obtenerCHSDif((*listaEjecutar)->info->sector,datosConfig,proximoSector );

	aux = (*listaEjecutar);
	while(aux != NULL && aux->info != NULL)
	{
		proximo = proximoSector->c - (*posicionActual)->c;
		 obtenerCHSDif(aux->info->sector,datosConfig,evaluandoSector );
		evaluando = evaluandoSector->c - (*posicionActual)->c;

		if((*sentidoGiro) == 1)
		{
			if (aux->info->tipoOperacion != omitir->tipoOperacion &&
					aux->info->sector != omitir->sector)
			{
				if(evaluando >= 0 && proximo > evaluando)
				{
					proximoSector->c = evaluandoSector->c;
					proximoSector->h = evaluandoSector->h;
					proximoSector->s = evaluandoSector->s;
					proximoSector->seekTime = evaluandoSector->seekTime;
					resultado = aux->info;
				}
			}
		}
		else if((*sentidoGiro) == -1)
		{
			if (aux->info->tipoOperacion != omitir->tipoOperacion &&
							aux->info->sector != omitir->sector)
			{
				if(evaluando <= 0 && proximo < evaluando)
				{
					proximoSector->c = evaluandoSector->c;
					proximoSector->h = evaluandoSector->h;
					proximoSector->s = evaluandoSector->s;
					proximoSector->seekTime = evaluandoSector->seekTime;
					resultado = aux->info;
				}
			}
		}
//verificar si hay alguno qe cumplio si no, fin  y dar vuelta el sentido
//y volver a asginar a aux...
		if(aux->sgte == NULL)
		{
			if((*sentidoGiro) == 1 && proximo < 0)
			{

				aux = (*listaEjecutar);
				(*sentidoGiro) = -1;
				(*posicionActual)->c = datosConfig.c -1;
				obtenerCHSDif(aux->info->sector,datosConfig,proximoSector);
			}
			else if((*sentidoGiro) == -1 && proximo > 0)
			{

				aux = (*listaEjecutar);
				(*sentidoGiro) = 1;
				(*posicionActual)->c = 0;
				obtenerCHSDif(aux->info->sector,datosConfig,proximoSector);
			}
			else
			{
				break;
			}
		}
		aux= aux->sgte;
	//	if(evaluandoSector != NULL)
		//	free(evaluandoSector);
	}

//TODO: REVISAR FREE URGENTE!!!
	free(proximoSector);
		free(evaluandoSector);

	return resultado;
}


int32_t buscarSectorListaSincro (stPedido *pedido,stNodoSincro **listaSincro)
{
	stNodoSincro *aux,*anterior;

	if ((*listaSincro) != NULL && (*listaSincro)->sector == pedido->sector)
	{
		return 1;
	}

	aux = (*listaSincro);

	while(aux != NULL && aux->sector != NULL)
	{
		anterior = aux;
		aux = aux->sgte;
		if(aux != NULL && aux->sector == pedido->sector)
		{
			free(aux);
			return 1;
		}
	}
	free(aux);

	return 0;
}


/*
chs *obtenerCHS(long sector, chs datosConfig)
{
	chs* resultado =(chs *)malloc(sizeof(chs));
	int32_t resto = sector%(datosConfig.h*datosConfig.s);
	resultado->c = sector/(datosConfig.h*datosConfig.s);
	//resultado->h = resto/datosConfig.s; ESTE ES EL CALCULO DE COMO DEBERIA IR LO COMENTAMOS PORQUE SEGUN LO QUE DICEN EN EL FORO HAY QUE CLAVARLE UN 1 SIEMPRE
	resultado->h = 1;
	resultado->s = resto%datosConfig.s;
	return resultado;
}*/


void obtenerCHSDif(long sector, chs datosConfig,chs *resultado)
{
	int32_t resto = sector%(datosConfig.h*datosConfig.s);
	resultado->c = sector/(datosConfig.h*datosConfig.s);
	resultado->h = 1;
	resultado->s = resto%datosConfig.s;
}
